package jsonpatch

import (
	"github.com/appscode/jsonpatch"
	"operator/pkg/util"
	"strings"
)

type PatchOperation struct {
	ops []jsonpatch.Operation
}

func (p *PatchOperation) ToByte() []byte {
	return []byte(util.JsonEncode(p.ops))
}

func (p *PatchOperation) ToString() string {
	return util.JsonEncode(p.ops)
}

func (p *PatchOperation) Empty() bool {
	return len(p.ops) == 0
}

func (p *PatchOperation) Operation() []jsonpatch.Operation {
	return p.ops
}

func (p *PatchOperation) ToArray() []map[string]interface{} {
	result := make([]map[string]interface{}, 0, 10)
	for _, i := range p.ops {
		m := util.JsonDecode(util.JsonEncode(i)).(map[string]interface{})
		result = append(result, m)
	}

	return result
}

func (p *PatchOperation) Contains(path string, like bool) bool {
	for _, i := range p.ops {
		if like {
			if strings.Contains(i.Path, path) {
				return true
			}
			return false
		}

		if i.Path == path {
			return true
		}
	}

	return false
}

func JsonPatch(old, new interface{}) *PatchOperation {
	oldbyte := []byte{}
	newbyte := []byte{}

	switch old.(type) {
	case string:
		oldbyte = []byte(old.(string))
	case []byte:
		oldbyte = old.([]byte)
	default:
		m := util.JsonEncode(old)
		oldbyte = []byte(m)
	}

	switch new.(type) {
	case string:
		newbyte = []byte(new.(string))
	case []byte:
		newbyte = new.([]byte)
	default:
		m := util.JsonEncode(new)
		newbyte = []byte(m)
	}

	operation, err := jsonpatch.CreatePatch(oldbyte, newbyte)
	if err != nil {
		return nil
	}

	return &PatchOperation{
		ops: operation,
	}
}
